#ifndef __M_HOST_H__
#define __M_HOST_H__
#include "mq_exchange.hpp"
#include "mq_queue.hpp"
#include "mq_binding.hpp"
#include "mq_message.hpp"

namespace bitmq{
    class VirtualHost {
    public:
    using ptr = std::shared_ptr<VirtualHost>;
    VirtualHost(const std::string &hname, const std::string &basedir, const std::string &dbfile) : _host_name(hname),
     _emp(std::make_shared<ExchangeManager>(dbfile)),
     _mqmp(std::make_shared<MsgQueueManager>(dbfile)),
     _bmp(std::make_shared<BindingManager>(dbfile)),
     _mmp(std::make_shared<MessageManager>(basedir))
    {
        // 获取到所有的队列信息，通过队列名称恢复历史消息数据
        QueueMap qm = _mqmp->allQueues();
        for (auto &q : qm)
        {
            _mmp->initQueueMessage(q.first);
        }
    }
    bool declareExchange(const std::string &name,
        ExchangeType type, bool durable, bool auto_delete,
        const google::protobuf::Map<std::string, std::string> &args){
            return (_emp->declareExchange(name,type,durable,auto_delete,args));
        }
   void deleteExchange(const std::string &ename) {
            //删除交换机的时候，需要将交换机相关的绑定信息也删除掉
            _bmp->removeExchangeBindings(ename);
            _emp->deleteExchange(ename);
        }
    bool existsExchange(const std::string &ename) {
            return _emp->exists(ename);
        }
    ExChange::ptr selectExchange(const std::string &ename) {
            return _emp->selectExchange(ename);
    }
    bool declareQueue(const std::string &qname, 
        bool qdurable, 
        bool qexclusive,
        bool qauto_delete,
        const google::protobuf::Map<std::string, std::string> &qargs) {
        //初始化队列的消息句柄（消息的存储管理）
        //队列的创建
        bool ret = _mqmp->declareQueue(qname, qdurable, qexclusive, qauto_delete, qargs);
        _mmp->initQueueMessage(qname);
        return ret;
    }
    void deleteQueue(const std::string &name) {
        //删除的时候队列相关的数据有两个：队列的消息，队列的绑定信息
        _mmp->destroyQueueMessage(name);
        _bmp->removeMsgQueueBindings(name);
        return _mqmp->deleteQueue(name);
    }
    bool existsQueue(const std::string &name) {
        return _mqmp->exists(name);
    }
    QueueMap allQueues() {
        return _mqmp->allQueues();
    }

    bool bind(const std::string &ename, const std::string &qname, const std::string &key) {
        ExChange::ptr ep = _emp->selectExchange(ename);
        if (ep.get() == nullptr) {
            DLOG("进行队列绑定失败，交换机%s不存在！", ename.c_str());
            return false;
        }
        MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
        if (mqp.get() == nullptr) {
            DLOG("进行队列绑定失败，队列%s不存在！", qname.c_str());
            return false;
        }
        //绑定消息的持久化存储也受到交换机和队列的持久化影响，两个当中一个不持久化，绑定消息也不能持久化
        return _bmp->bind(ename, qname, key, ep->durable && mqp->durable);
    }
    void unBind(const std::string &ename, const std::string &qname) {
        return _bmp->unBind(ename, qname);
    }
    MsgQueueBindingMap exchangeBindings(const std::string &ename) {
        return _bmp->getExchangeBindings(ename);
    }
    bool existsBinding(const std::string &ename, const std::string &qname) {
        return _bmp->exists(ename, qname);
    }
    bool basicPublish(const std::string &qname, BasicProperties *bp, const std::string &body) {
        MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
        if (mqp.get() == nullptr) {
            DLOG("发布消息失败，队列%s不存在！", qname.c_str());
            return false;
        }
        DeliverMode value=UNDURABLE;
        if(mqp->durable == true) value=DURABLE;
        return _mmp->insertMessage(qname, bp, body, value);
    }
    MessagePtr basicConsume(const std::string &qname) {
        return _mmp->front(qname);
    }
    void basicAck(const std::string &qname, const std::string &msgid) {
        return _mmp->ack(qname, msgid);
    }  
    void clear() {
        _emp->clear();
        _mqmp->clear();
        _bmp->clear();
        _mmp->clear();
    } 
    private:
    std::string _host_name;//虚拟机名称
    ExchangeManager::ptr _emp;//交换机管理句柄，可以获得所有交换机成员和执行管理交换机操作
    MsgQueueManager::ptr _mqmp;//队列管理句柄，可以获得所有队列成员和执行管理队列操作
    BindingManager::ptr _bmp;//绑定信息管理句柄，可以获得所有的绑定信息和执行管理绑定信息的操作
    MessageManager::ptr _mmp;//消息数据管理句柄，可以获得所有队列的消息和执行管理各个队列消息的操作
    };
}
#endif